package com.elastic.diff;

import com.elastic.mapping.ClientFactory;
import com.elastic.mapping.createIndexWithMapping;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Requests;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by xi on 2018/1/27.
 */
public class DiffTermAndMatch {

    private static void createTestIndex(String index){
        createIndexWithMapping.createIndex(index);
    }

    public static void createTestMapping(String indices,String mappingType)throws Exception{
        XContentBuilder builder=XContentFactory.jsonBuilder()
                .startObject()
                  .startObject(mappingType)//表的名字
                    .startObject("properties")
                    .startObject("fullText").field("type","string").endObject()
                    .startObject("exactValue").field("type", "string").field("store", "yes").field("index", "not_analyzed").endObject()
                   .endObject()
                  .endObject()
                .endObject();
        System.out.println(builder.toString());
        PutMappingRequest mapping = Requests.putMappingRequest(indices).type(mappingType).source(builder);
        ClientFactory.getInstance().admin().indices().putMapping(mapping).actionGet();
    }

    /**
     * 转换成json对象 json=={"id":"1","name":"aa","age":"20"}
     * @return
     */
    private static String insertJson(MyType myType) {
        String json = "";
        try {
            XContentBuilder contentBuilder = XContentFactory.jsonBuilder()
                    .startObject();
            contentBuilder.field("fullText", myType.getFullText());
            contentBuilder.field("exactValue", myType.getExactValue());
            json = contentBuilder.endObject().string();
            System.out.println("json==" + json);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }
    public static void craeteTestData(String index,String type){
        for(int i=0;i<1;i++){
            try {
                MyType myType = new MyType();
                myType.setFullText("Quick Foxes!");
                myType.setExactValue("Quick Foxes!");
                IndexResponse response = ClientFactory.getInstance().prepareIndex(index, type, String.valueOf(i))
                        .setSource(insertJson(myType)).execute().actionGet();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public static void craeteTestData2(String index,String type,String termContent){
        for(int i=10;i<11;i++){
            try {
                MyType myType = new MyType();
                myType.setFullText("Quick Foxes!");
                myType.setExactValue(termContent);//大小字母，通过term 能查询到吗
                IndexResponse response = ClientFactory.getInstance().prepareIndex(index, type, String.valueOf(i))
                        .setSource(insertJson(myType)).execute().actionGet();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws   Exception{
        String indexName="myindex";
        String type ="mytype";
        String temp ="A";
        if(!createIndexWithMapping.isIndexExists(indexName)){
            createTestIndex(indexName);
            createTestMapping(indexName, type);
            craeteTestData(indexName, type);
            craeteTestData2(indexName,type,temp);
        }
//        termQueryAnalyzed(indexName, type, "Quick Foxes!");//0
//        termQueryAnalyzed(indexName, type, "Foxes");//0
//        termQueryAnalyzed(indexName, type, "foxes");//1  分词的结果，默认都转成小写了，通过这个能搜索到
          //termQueryNotAnalyzed(indexName,type,"Quick Foxes"); //搜索不分词的字段的情况，需要搜索完整的词语,少个字符都不行，Quick Foxes! 少了！也搜索不到

         //注意：不要match-query 和query-string 来查询，默认会先对查询的词做分词
        //queryStringAnalyzed(indexName, type, "Quick Foxes!");//解析报错，不能有特殊字符
        //queryStringAnalyzed(indexName, type, "Foxes");//2 默认会把传入进来的字符先分词，然后和数据库比较分词就小写foxes
        //queryStringAnalyzed(indexName, type, "foxes");//2  分词的结果，默认都转成小写了，通过这个能搜索到

        //matchQueryAnalyzed(indexName, type, "Quick Foxes!");//解析报错，不能有特殊字符
        //matchQueryAnalyzed(indexName, type, "Foxes");//2 默认会把传入进来的字符先分词，然后和数据库比较分词就小写foxes
        //matchQueryAnalyzed(indexName, type, "foxes");//2  分词的结果，默认都转成小写了，通过这个能搜索到

         matchQueryNotAnalyzed(indexName, type, "a");
    }

    public static void termQueryAnalyzed(String indexKey,String type,String queryContent){
        SearchRequestBuilder searchBuilder = ClientFactory.getInstance().prepareSearch(indexKey);//指定多个数据库
        searchBuilder.setTypes(type);
        QueryBuilder qb = QueryBuilders.termQuery("fullText", queryContent);
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();

        //and搜索条件
        SearchResponse searchResponse = searchBuilder
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setFrom(0).setSize(100).setExplain(false)
                .setQuery(qb)
                .execute()
                .actionGet();
        SearchHits hits = searchResponse.getHits();
        long totalCount = hits.getHits().length;
        System.out.println("totalCount==="+totalCount);
        for (int i = 0; i < totalCount; i++) {
            System.out.println("termQueryAnalyzed result:hits.getAt(i).getSource():"+hits.getAt(i).getSource());
        }
    }
    public static void queryStringAnalyzed(String indexKey,String type,String queryContent){
        SearchRequestBuilder searchBuilder = ClientFactory.getInstance().prepareSearch(indexKey);//指定多个数据库
        searchBuilder.setTypes(type);
        QueryBuilder qb =  QueryBuilders.queryStringQuery(queryContent).defaultField("fullText");
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();

        //and搜索条件
        SearchResponse searchResponse = searchBuilder
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setFrom(0).setSize(100).setExplain(false)
                .setQuery(qb)
                .execute()
                .actionGet();
        SearchHits hits = searchResponse.getHits();
        long totalCount = hits.getHits().length;
        System.out.println("totalCount==="+totalCount);
        for (int i = 0; i < totalCount; i++) {
            System.out.println("queryStringBuilder result:hits.getAt(i).getSource():"+hits.getAt(i).getSource());
        }
    }


    public static void matchQueryAnalyzed(String indexKey,String type,String queryContent){
        SearchRequestBuilder searchBuilder = ClientFactory.getInstance().prepareSearch(indexKey);//指定多个数据库
        searchBuilder.setTypes(type);
        QueryBuilder qb = QueryBuilders.matchQuery("fullText", queryContent);
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();

        //and搜索条件
        SearchResponse searchResponse = searchBuilder
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setFrom(0).setSize(100).setExplain(false)
                .setQuery(qb)
                .execute()
                .actionGet();
        SearchHits hits = searchResponse.getHits();
        long totalCount = hits.getHits().length;
        System.out.println("totalCount==="+totalCount);
        for (int i = 0; i < totalCount; i++) {
            System.out.println("termQueryAnalyzed result:hits.getAt(i).getSource():"+hits.getAt(i).getSource());
        }
    }

    public static void termQueryNotAnalyzed(String indexKey,String type,String content){
        QueryBuilder qb = QueryBuilders.termQuery("exactValue", content);

        SearchRequestBuilder searchBuilder = ClientFactory.getInstance().prepareSearch(indexKey);//指定多个数据库
        searchBuilder.setTypes(type);
        searchBuilder.setQuery(qb);

        //and搜索条件
        SearchResponse searchResponse = searchBuilder
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setFrom(0).setSize(100).setExplain(false)
                .execute()
                .actionGet();
        System.out.println("toString:"+searchBuilder.toString());
        SearchHits hits = searchResponse.getHits();
        long end = new Date().getTime();
        long totalCount = hits.getHits().length;
        System.out.println("termQueryNotAnalyzed count;"+totalCount);
        for (int i = 0; i < totalCount; i++) {
            System.out.println("termQueryNotAnalyzed resul : thits.getAt(i).getSource():"+hits.getAt(i).getSource());
        }
    }


    /**
            * 默认的standard analyzer分词规则：<br>
    * 去掉大部分标点符号，并以此分割原词为多个词，把分分割后的词转为小写放入token组中。<br>
    * 对于not-analyzed的词，直接把原词放入token组中。<br>
    *matchQuery的机制是：先检查字段类型是否是analyzed，如果是，则先分词，再去去匹配token；如果不是，则直接去匹配token。<br>
    * id=id2，默认分词，id2不分词。<br>
    * 以wwIF5-vP3J4l3GJ6VN3h为例：<br>
    * id是的token组是[wwif5,vp3j4l3gj6vn3h]<br>
    * id2的token组是[wwIF5-vP3J4l3GJ6VN3h]<br>
    * 可以预计以下结果：<br>
    * 1.matchQuery("id", "字符串")，"字符串"分词后有[wwif5,vp3j4l3gj6vn3h]其中之一时，有值。<br>
    * 如：wwIF5-vP3J4l3GJ6VN3h,wwif5-vp3j4l3gj6vn3h,wwIF5,wwif5,wwIF5-6666等等。<br>
    * 2.matchQuery("id2", "wwIF5-vP3J4l3GJ6VN3h")，有值。<br>
    * 特别说明：<br>
    * 在创建索引时，如果没有指定"index":"not_analyzed"<br>
    * 会使用默认的analyzer进行分词。当然你可以指定analyzer。<br>
    * 在浏览器中输入：<br>
    * http://localhost:9200/_analyze?pretty&analyzer=standard&text=J4Kz1%26L*bvjoQFE9gHC7H<br>
    * 可以看到J4Kz1&LbvjoQFE9gHC7H被分成了：j4kz1和lbvjoqfe9ghc7h<br>
    * %26是&符号，&?等符号是浏览器特殊符号，你懂的，可以用其它符号代替查看结果。<br>
     *     exactValue 是不分词的字段
    */
    public static void matchQueryNotAnalyzed(String indexKey,String type,String content){
        QueryBuilder qb = QueryBuilders.matchQuery("exactValue", content);

        SearchRequestBuilder searchBuilder = ClientFactory.getInstance().prepareSearch(indexKey);//指定多个数据库
        searchBuilder.setTypes(type);
        searchBuilder.setQuery(qb);

        //and搜索条件
        SearchResponse searchResponse = searchBuilder
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setFrom(0).setSize(100).setExplain(false)
                .execute()
                .actionGet();
        System.out.println("toString:"+searchBuilder.toString());
        SearchHits hits = searchResponse.getHits();
        long end = new Date().getTime();
        long totalCount = hits.getHits().length;
        System.out.println("matchQueryNotAnalyzed count;"+totalCount);
        for (int i = 0; i < totalCount; i++) {
            System.out.println("matchQueryNotAnalyzed resul : thits.getAt(i).getSource():"+hits.getAt(i).getSource());
        }
    }



}
